﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using InkFx.WinControl.Utils;
using DA = InkFx.WinControl.XIDEAlignment;
using DTGS = InkFx.WinControl.XIDEGroupState;

namespace InkFx.WinControl
{
    public class XIDESplitControl : IDisposable
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="idePanel">Type: XIDEPanel</param>
        [Obsolete("不建议手动调用 XIDESplitControl 的构造函数", false)]
        public XIDESplitControl(XIDEPanel idePanel)
        {
            m_Panel1 = new XIDESplitPanel(this);
            m_Panel2 = new XIDESplitPanel(this);
            this.Name = XIDEPanel.NewName("ideSplitCtrl");
            this.m_IDEPanel = idePanel;
            if (idePanel != null) idePanel.RegSplitControl(this);

            this.SplitterWidth = XIDEPanel.SPLIT_SIZE;
            this.Panel1MinSize = this.Panel2MinSize = XIDEPanel.SPLIT_PANEL_MIN_SIZE;

            Tools.LogDebug(string.Format("XIDESplitControl 创建: Name='{0}' Type='{1}' ", this.Name, Tools.GetKnowTypeName(this.GetType())));
        }



        protected XIDEPanel m_IDEPanel;
        protected XIDESplitPanel m_Panel1;
        protected XIDESplitPanel m_Panel2; 
        private string m_Name = string.Empty;
        protected int m_SplitterWidth = 4;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_Panel1Size = -1;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected int m_Panel2Size = -1;

        protected Rectangle m_Bounds = Rectangle.Empty;
        protected int m_Panel1MinSize = 25;
        protected int m_Panel2MinSize = 25;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_StopSplitter;

        public string Name
        {
            get { return m_Name; }
            set { m_Name = (value + "").Trim(); }
        }

        public int SplitterWidth
        {
            get { return m_SplitterWidth; }
            set { m_SplitterWidth = Math.Max(2, value); }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(25), Localizable(true), RefreshProperties(RefreshProperties.All)]
        public int Panel1MinSize
        {
            get
            {
                return this.m_Panel1MinSize;
            }
            set
            {
                if (value < 0) value = 0;
                if (value == this.Panel1MinSize) return;
                this.m_Panel1MinSize = value;
                this.ResetRect();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        [SRCategory("布局"), DefaultValue(25), Localizable(true), RefreshProperties(RefreshProperties.All)]
        public int Panel2MinSize
        {
            get
            {
                return this.m_Panel2MinSize;
            }
            set
            {
                if (value < 0) value = 0;
                if (value == this.Panel2MinSize) return;
                this.m_Panel2MinSize = value;
                this.ResetRect();
            }
        }

        public FixedPanel FixedPanel { get; set; }
        public Orientation Orientation { get; set; }


        public Rectangle Bounds
        {
            get { return m_Bounds; }
            set
            {
                m_Bounds = value;
                this.InitFixedPanel();
                this.ResetRect();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public virtual InkFx.WinControl.XIDEPanel IDEPanel
        {
            get { return m_IDEPanel; }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public XIDESplitPanel Panel1
        {
            get { return m_Panel1; }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public XIDESplitPanel Panel2
        {
            get { return m_Panel2; }
        }

        public bool Panel1Hidden
        {
            get
            {
                var panel1 = this.Panel1;
                return panel1 == null || panel1.IsHidden;
            }
        }
        public bool Panel2Hidden
        {
            get
            {
                var panel2 = this.Panel2;
                return panel2 == null || panel2.IsHidden;
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public bool IsDisposed { get; private set; }
        /// <summary>
        /// 返回 被固定尺寸 的那个 Panel 的尺寸
        /// <para>如果 FixedPanel==Panel2, 则返回 Panel2 的尺寸, 否则返回 Panel1 的尺寸</para>
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual int FixedPanelSize
        {
            get
            {
                if (FixedPanel == FixedPanel.Panel2) { return m_Panel2Size; }
                return m_Panel1Size;
            }
            set
            {
                var bound = new Rectangle(Point.Empty, this.Bounds.Size);  //这里不能用 var bound = this.Bounds;
                var orientation = this.Orientation;
                var splitterWidth = this.SplitterWidth;
                var size = (orientation == Orientation.Horizontal) ? bound.Height : bound.Width;

                if (FixedPanel == FixedPanel.Panel2) { m_Panel2Size = value; m_Panel1Size = size - splitterWidth - value; }
                else { m_Panel1Size = value; m_Panel2Size = size - splitterWidth - value; }

                this.ResetRect();
            }
        }

        /// <summary>
        /// 重新计算 各种区域边界
        /// </summary>
        public virtual void ResetRect()
        {
            var panel1 = this.Panel1;
            var panel2 = this.Panel2;
            var child1 = panel1.Child;
            var child2 = panel2.Child;
            if (child1 is XIDEGroup && ((XIDEGroup)child1).IsDisposed) { panel1.SetChild(null); child1 = null; }
            if (child2 is XIDEGroup && ((XIDEGroup)child2).IsDisposed) { panel2.SetChild(null); child2 = null; }
            if (child1 is XIDESplitControl && ((XIDESplitControl)child1).IsDisposed) { panel1.SetChild(null); child1 = null; }
            if (child2 is XIDESplitControl && ((XIDESplitControl)child2).IsDisposed) { panel2.SetChild(null); child2 = null; }

            this.BaseResetRect();

            if (child1 is XIDEGroup && ((XIDEGroup)child1).IsDisposed) { panel1.SetChild(null); child1 = null; }
            if (child2 is XIDEGroup && ((XIDEGroup)child2).IsDisposed) { panel2.SetChild(null); child2 = null; }
            if (child1 is XIDESplitControl && ((XIDESplitControl)child1).IsDisposed) { panel1.SetChild(null); child1 = null; }
            if (child2 is XIDESplitControl && ((XIDESplitControl)child2).IsDisposed) { panel2.SetChild(null); child2 = null; }



            var panel1G = child1 as XIDEGroup;
            var panel2G = child2 as XIDEGroup;
            if (panel1G != null && panel1G.State == XIDEGroupState.Expand && !panel1G.m_SizeIsSmall) { panel1G.Dock = DockStyle.None; panel1G.BaseParent = this.IDEPanel; }
            if (panel2G != null && panel2G.State == XIDEGroupState.Expand && !panel2G.m_SizeIsSmall) { panel2G.Dock = DockStyle.None; panel2G.BaseParent = this.IDEPanel; }
            if (panel1G != null && panel1G.State == XIDEGroupState.Collapse) { panel1G.Dock = DockStyle.None; panel1G.BaseParent = null; }
            if (panel2G != null && panel2G.State == XIDEGroupState.Collapse) { panel2G.Dock = DockStyle.None; panel2G.BaseParent = null; }


            //var group1 = panel1.Group;
            //var group2 = panel2.Group;
            //if (group1 != null && !group1.Visible) { group1.BaseParent = null; }
            //if (group2 != null && !group2.Visible) { group2.BaseParent = null; }
        }

        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_InitFixedPanel = false;
        /// <summary>
        /// 
        /// </summary>
        protected internal virtual void InitFixedPanel()
        {
            if (m_InitFixedPanel) return;

            var idePanel = this.IDEPanel;
            if (idePanel == null) return;
            var bounds = this.Bounds;
            if (bounds.Width <= 0 && bounds.Height <= 0) return;

            bool center1 = this.Panel1.ContainsCenter;
            bool center2 = this.Panel2.ContainsCenter;
            var init = (this.Panel1.Child != null && this.Panel2.Child != null)
                       || (this.Panel1.Child != null && center2)
                       || (this.Panel2.Child != null && center1);
            if (!init) return;

            const int size = XIDEPanel.DEFAULT_GROUP_SIZE;
            if (center1 && !center2)
            {
                int minDistance = this.Panel1MinSize;
                this.FixedPanel = FixedPanel.Panel2;
                this.SplitterDistance = Math.Max(minDistance, (this.IsHorizontal ? bounds.Height : bounds.Width) - size);
            }
            else if (center2 && !center1)
            {
                int maxDistance = bounds.Width - this.Panel2MinSize;
                this.FixedPanel = FixedPanel.Panel1;
                this.SplitterDistance = Math.Min(maxDistance, size);
            }
            else
            {
                this.FixedPanel = FixedPanel.None;
                this.SplitterDistance = this.IsHorizontal ? (bounds.Height - this.SplitterWidth) / 2 : (bounds.Width - this.SplitterWidth) / 2;
            }

            m_InitFixedPanel = true;
        }

        public virtual int SplitterDistance
        {
            get
            {
                if (this.Orientation == Orientation.Horizontal)
                    return (m_RectPanel1.Height >= 1) ? m_RectPanel1.Height : this.m_Panel1Size;
                else
                    return (m_RectPanel1.Width >= 1) ? m_RectPanel1.Width : this.m_Panel1Size;
            }
            set
            {
                if (value < 0) value = 0;
                this.m_Panel1Size = value;
                this.m_Panel2Size = -1;
                this.ResetRect();
            }
        }

        #region  区 域 坐 标

        /// <summary>
        /// 内部字段
        /// </summary>
        protected bool m_ResetRect = false;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectFull = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectMin = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectPanel1 = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectPanel2 = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectSplitter = Rectangle.Empty;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected Rectangle m_RectSplitRange = Rectangle.Empty;

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle RectPanel1
        {
            get { return m_RectPanel1; }
        }
        /// <summary>
        /// 
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle RectPanel2
        {
            get { return m_RectPanel2; }
        }
        /// <summary>
        /// 获取分割条 相对控件本身的 最终区域
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle SplitterRectangle
        {
            get { return m_RectSplitter; }
        }
        /// <summary>
        /// 获取分割条 执行分割时 可以拖拽的范围
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Rectangle RectSplitRange
        {
            get { return m_RectSplitRange; }
        }


        public virtual void BaseResetRect()
        {
            var panel1 = this.m_Panel1;
            var panel2 = this.m_Panel2;
            if (panel1 == null || panel2 == null) return;
            //if (!this.IsHandleCreated) return;

            var bound = this.Bounds;
            var fixedPanel = this.FixedPanel;
            var orientation = this.Orientation;
            var splitterWidth = this.SplitterWidth;
            var panel1MinSize = this.Panel1MinSize;
            var panel2MinSize = this.Panel2MinSize;
            var hidden1 = this.Panel1Hidden;
            var hidden2 = this.Panel2Hidden;
            var panel1Size = this.m_Panel1Size;
            var panel2Size = this.m_Panel2Size;
            //if (bound.Width <= 0 || bound.Height <= 0) { return; } //2021-03-25 本行代码一定要注释, 否则子控件的区域将会计算错误

            if (m_ResetRect) return;

            try
            {
                m_ResetRect = true;
                if (orientation == Orientation.Horizontal)
                {
                    #region  上 下 分 割

                    m_RectMin = new Rectangle(bound.X, bound.Y, bound.Width, splitterWidth + panel1MinSize + panel2MinSize);
                    m_RectFull = new Rectangle(bound.X, bound.Y, bound.Width, bound.Height);

                    if (panel2Size < 0) panel2Size = m_Panel2Size = bound.Height - splitterWidth - panel1Size;

                    int height1 = 0, height2 = 0, heightS = splitterWidth;
                    if (fixedPanel == FixedPanel.Panel1) { height1 = panel1Size; }
                    else if (fixedPanel == FixedPanel.Panel2) { height1 = bound.Height - heightS - panel2Size; }
                    else if (fixedPanel == FixedPanel.None)
                    {
                        double rate = (m_Panel1Size <= 0 || m_Panel2Size <= 0) ? -1 : (double)m_Panel1Size / (double)(m_Panel1Size + m_Panel2Size);
                        height1 = (rate < 0 || rate > 1) ? panel1Size : (int)Math.Ceiling((bound.Height - heightS) * rate);
                    }
                    height2 = bound.Height - height1 - heightS;
                    this.m_StopSplitter = (m_Panel1MinSize + m_Panel2MinSize + heightS) > bound.Height;

                    if (fixedPanel != FixedPanel.None)
                    {
                        if (fixedPanel == FixedPanel.Panel2)
                        {
                            if (height1 < m_Panel1MinSize) { height1 = m_Panel1MinSize; height2 = Math.Max(0, bound.Height - height1 - heightS); height1 = bound.Height - height2 - (m_StopSplitter ? 0 : heightS); }
                            if (height2 < m_Panel2MinSize) { height2 = m_Panel2MinSize; height1 = Math.Max(0, bound.Height - height2 - heightS); height2 = bound.Height - height1 - (m_StopSplitter ? 0 : heightS); }
                        }
                        else if (fixedPanel == FixedPanel.Panel1)
                        {
                            if (height2 < m_Panel2MinSize) { height2 = m_Panel2MinSize; height1 = Math.Max(0, bound.Height - height2 - heightS); height2 = bound.Height - height1 - (m_StopSplitter ? 0 : heightS); }
                            if (height1 < m_Panel1MinSize) { height1 = m_Panel1MinSize; height2 = Math.Max(0, bound.Height - height1 - heightS); height1 = bound.Height - height2 - (m_StopSplitter ? 0 : heightS); }
                        }
                    }
                    if (height1 < XIDEGroup.MIN_SHOW_HEIGHT || height2 < XIDEGroup.MIN_SHOW_HEIGHT)
                    {
                        this.m_StopSplitter = true;
                        heightS = 0;
                        if (fixedPanel == FixedPanel.Panel2) { height2 = bound.Height; height1 = 0; }
                        else { height1 = bound.Height; height2 = 0; }
                    }


                    m_RectPanel1 = new Rectangle(bound.X, bound.Y, bound.Width, height1);
                    m_RectSplitter = new Rectangle(bound.X, m_RectPanel1.Bottom, bound.Width, heightS);
                    m_RectPanel2 = new Rectangle(bound.X, m_RectSplitter.Bottom, bound.Width, height2);

                    if (hidden1) { m_RectPanel1 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel2 = m_RectFull; }
                    if (hidden2) { m_RectPanel2 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel1 = m_RectFull; }
                    m_RectSplitRange = (m_RectSplitter.Width <= 0 || m_RectSplitter.Height <= 0) ? Rectangle.Empty : new Rectangle(bound.X, bound.Y + m_Panel1MinSize, bound.Width, bound.Height - m_Panel1MinSize - m_Panel2MinSize);

                    m_Panel1.Bounds = m_RectPanel1;
                    m_Panel2.Bounds = m_RectPanel2;

                    #endregion
                }
                else
                {
                    #region  左 右 分 割

                    m_RectMin = new Rectangle(bound.X, bound.Y, splitterWidth + panel1MinSize + panel2MinSize, bound.Height);
                    m_RectFull = new Rectangle(bound.X, bound.Y, bound.Width, bound.Height);

                    if (panel2Size < 0) panel2Size = m_Panel2Size = bound.Width - splitterWidth - panel1Size;


                    int width1 = 0, width2 = 0, widthS = splitterWidth;
                    if (fixedPanel == FixedPanel.Panel1) { width1 = panel1Size; }
                    else if (fixedPanel == FixedPanel.Panel2) { width1 = bound.Width - widthS - panel2Size; }
                    else if (fixedPanel == FixedPanel.None)
                    {
                        double rate = (m_Panel1Size <= 0 || m_Panel2Size <= 0) ? -1 : (double)m_Panel1Size / (double)(m_Panel1Size + m_Panel2Size);
                        width1 = (rate < 0 || rate > 1) ? panel1Size : (int)Math.Ceiling((bound.Width - widthS) * rate);
                    }
                    width2 = bound.Width - width1 - widthS;
                    this.m_StopSplitter = (m_Panel1MinSize + m_Panel2MinSize + widthS) > bound.Width;

                    if (fixedPanel != FixedPanel.None)
                    {
                        if (fixedPanel == FixedPanel.Panel2)
                        {
                            if (width1 < m_Panel1MinSize) { width1 = m_Panel1MinSize; width2 = Math.Max(0, bound.Width - width1 - widthS); width1 = bound.Width - width2 - (m_StopSplitter ? 0 : widthS); }
                            if (width2 < m_Panel2MinSize) { width2 = m_Panel2MinSize; width1 = Math.Max(0, bound.Width - width2 - widthS); width2 = bound.Width - width1 - (m_StopSplitter ? 0 : widthS); }
                        }
                        else if (fixedPanel == FixedPanel.Panel1)
                        {
                            if (width2 < m_Panel2MinSize) { width2 = m_Panel2MinSize; width1 = Math.Max(0, bound.Width - width2 - widthS); width2 = bound.Width - width1 - (m_StopSplitter ? 0 : widthS); }
                            if (width1 < m_Panel1MinSize) { width1 = m_Panel1MinSize; width2 = Math.Max(0, bound.Width - width1 - widthS); width1 = bound.Width - width2 - (m_StopSplitter ? 0 : widthS); }
                        }
                    }
                    if (width1 < XIDEGroup.MIN_SHOW_WIDTH || width2 < XIDEGroup.MIN_SHOW_WIDTH)
                    {
                        this.m_StopSplitter = true;
                        widthS = 0;
                        if (fixedPanel == FixedPanel.Panel2) { width2 = bound.Width; width1 = 0; }
                        else { width1 = bound.Width; width2 = 0; }
                    }

                    
                    m_RectPanel1 = new Rectangle(bound.X, bound.Y, width1, bound.Height);
                    m_RectSplitter = new Rectangle(m_RectPanel1.Right, bound.Y, widthS, bound.Height);
                    m_RectPanel2 = new Rectangle(m_RectSplitter.Right, bound.Y, width2, bound.Height);

                    if (hidden1) { m_RectPanel1 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel2 = m_RectFull; }
                    if (hidden2) { m_RectPanel2 = Rectangle.Empty; m_RectSplitter = Rectangle.Empty; m_RectPanel1 = m_RectFull; }
                    m_RectSplitRange = (m_RectSplitter.Width <= 0 || m_RectSplitter.Height <= 0) ? Rectangle.Empty : new Rectangle(m_Panel1MinSize + bound.X, bound.Y, bound.Width - m_Panel1MinSize - m_Panel2MinSize, bound.Height);

                    m_Panel1.Bounds = m_RectPanel1;
                    m_Panel2.Bounds = m_RectPanel2; 

                    #endregion
                }
            }
            finally { m_ResetRect = false; }

            //if (this.DesignMode) { MessageBox.Show(this.m_Panel1Size + " | " + this.m_Panel2Size); }
        }

        #endregion


        #region  创建 或 销毁 XIDESplitControl

        /// <summary>
        /// 将 group1 与 group2 合并到一个 XIDESplitControl 中
        /// <para>group1 必须是已经存在且显示的 XIDEGroup</para>
        /// <para>group2 是即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</para>
        /// <para>align 是 group2 相对 group1 的方位</para>
        /// </summary>
        /// <param name="group1">已经存在且显示的 XIDEGroup</param>
        /// <param name="group2">即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</param>
        /// <param name="align">group2 相对 group1 的方位</param>
        /// <returns>如果融合成功 则返回 融合后的 XIDESplitControl</returns>
        public static XIDESplitControl DoSplit(XIDEGroup group1, XIDEGroup group2, DA align)
        {
            if (group1 == null) throw new ArgumentNullException("group1");
            if (group1.IDEPanel == null) throw new ArgumentNullException("group1.IDEPanel");
            if (group2 == null) throw new ArgumentNullException("group2");
            if (align == DA.Center) throw new InvalidOperationException("拆分操作时 XIDEAlignment 不能等于 Center");

            return DoSplitCore(group1.IDEPanel, group1, group2, align);
        }
        /// <summary>
        /// 将 split1 与 group2 合并到一个 XIDESplitControl 中
        /// <para>split1 必须是已经存在且显示的 XIDEGroup</para>
        /// <para>group2 是即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</para>
        /// <para>align 是 group2 相对 split1 的方位</para>
        /// </summary>
        /// <param name="split1">已经存在且显示的 XIDEGroup</param>
        /// <param name="group2">即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</param>
        /// <param name="align">group2 相对 split1 的方位</param>
        /// <returns>如果融合成功 则返回 融合后的 XIDESplitControl</returns>
        public static XIDESplitControl DoSplit(XIDESplitControl split1, XIDEGroup group2, DA align)
        {
            if (split1 == null) throw new ArgumentNullException("split1");
            if (split1.IDEPanel == null) throw new ArgumentNullException("split1.IDEPanel");
            if (group2 == null) throw new ArgumentNullException("group2");
            if (align == DA.Center) throw new InvalidOperationException("拆分操作时 XIDEAlignment 不能等于 Center");

            return DoSplitCore(split1.IDEPanel, split1, group2, align);
        }
        ///// <summary>
        ///// 将 center1 与 group2 合并到一个 XIDESplitControl 中
        ///// <para>center1 必须是已经存在且显示的 XIDEGroup</para>
        ///// <para>group2 是即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</para>
        ///// <para>align 是 group2 相对 center1 的方位</para>
        ///// </summary>
        ///// <param name="center1">已经存在且显示的 XIDEGroup</param>
        ///// <param name="group2">即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</param>
        ///// <param name="align">group2 相对 center1 的方位</param>
        ///// <returns>如果融合成功 则返回 融合后的 XIDESplitControl</returns>
        //public static XIDESplitControl DoSplit(XIDEPanelCenter center1, XIDEGroup group2, DA align)
        //{
        //    if (center1 == null) throw new ArgumentNullException("center1");
        //    if (center1.Parent == null) throw new ArgumentNullException("center1.Parent");
        //    if (center1.IDEPanel == null) throw new ArgumentNullException("center1.IDEPanel");
        //    if (group2 == null) throw new ArgumentNullException("group2");

        //    return DoSplitCore(center1.IDEPanel, center1, group2, align);
        //}

        /// <summary>
        /// 将 control 与 group2 合并到一个 XIDESplitControl 中
        /// <para>control 必须是已经存在且显示的 XIDEGroup 或 XIDESplitControl 或 XIDEPanelCenter</para>
        /// <para>group2 是即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</para>
        /// <para>align 是 group2 相对 control 的方位</para>
        /// </summary>
        /// <param name="idePanel">所属的 XIDEPanel 面板</param>
        /// <param name="control">已经存在且显示的 XIDEGroup 或 XIDESplitControl 或 XIDEPanelCenter</param>
        /// <param name="group2">即将加入的 XIDEGroup (一般 group2 正处于 浮动拖拽 的状态)</param>
        /// <param name="align">group2 相对 control 的方位</param>
        /// <returns>如果融合成功 则返回 融合后的 XIDESplitControl</returns>
        protected static XIDESplitControl DoSplitCore(XIDEPanel idePanel, object control, XIDEGroup group2, DA align)
        {
            if (control == group2) throw new InvalidOperationException("错误的操作");
            if (idePanel == null) throw new ArgumentNullException("idePanel");
            if (control == null) throw new ArgumentNullException("control");
            if (group2 == null) throw new ArgumentNullException("group2");
            //if (group2.Parent == null) throw new ArgumentNullException("group2.Parent");
            //if (group2.IDEPanel == null) throw new ArgumentNullException("group2.IDEPanel");
            if (!(control is XIDEGroup) && !(control is XIDESplitControl)) throw new ArgumentException("control 必须是 XIDEGroup | XIDESplitControl 两种类型的一种", "control");
            if (align == DA.Center) throw new InvalidOperationException("拆分操作时 XIDEAlignment 不能等于 Center");



            #region  如果 group1 和 group2 已经是 目标状态, 则不再执行任何逻辑




            #endregion


            #region  释放 group2 的额外资源

            //group2.ReleaseLogic();
            if (control is XIDEGroup) { var group1 = (XIDEGroup)control; group2.m_Alignment = group1.m_Alignment; }

            #endregion


            #region  执行 拆分逻辑

            var split = new XIDESplitControl(idePanel);
            split.IsHorizontal = (align == DA.Top || align == DA.Bottom);
            
            

            idePanel.TransLayout(() =>
            {
                if (control is XIDEGroup)
                {
                    var group1 = (XIDEGroup)control;
                    var panel = idePanel.FindParentPanel(group1);
                    var ctrl1 = group1;
                    var ctrl2 = group2;
                    if (align == DA.Left || align == DA.Top) { var temp = ctrl2; ctrl2 = ctrl1; ctrl1 = temp; }

                    if (panel != null) panel.SetChild(split);
                    split.Panel1.SetChild(ctrl1);
                    split.Panel2.SetChild(ctrl2);
                    group2.m_State = DTGS.Expand;
                }
                else if (control is XIDESplitControl)
                {
                    var split1 = (XIDESplitControl)control;
                    var panel = idePanel.FindParentPanel(split1);
                    object ctrl1 = split1;
                    object ctrl2 = group2;
                    if (align == DA.Left || align == DA.Top) { var temp = ctrl2; ctrl2 = ctrl1; ctrl1 = temp; }

                    if (panel != null) panel.SetChild(split);
                    split.Panel1.SetChild(ctrl1);
                    split.Panel2.SetChild(ctrl2);
                    group2.m_State = DTGS.Expand;
                }
            });
            return split;



            #endregion
        }

        /// <summary>
        /// 当前控件是否是 横向分割 (本属性是 Orientation 的 中转属性)
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Always)]
        public virtual bool IsHorizontal
        {
            get { return this.Orientation == Orientation.Horizontal; }
            set { this.Orientation = (value) ? Orientation.Horizontal : Orientation.Vertical; }
        }
        /// <summary>
        /// 如果当前 XIDESplitControl 中, 仅有 Panel1 或 Panel2 中包含控件, 则销毁当前 XIDESplitControl, 并将剩余控件转移到 父级中
        /// <para>返回参数 hide1 hide2 表示面板 Panel1 Panel1 是否应该隐藏</para>
        /// </summary>
        /// <param name="hide1">Panel1 是否应该处于 折叠状态</param>
        /// <param name="hide2">Panel2 是否应该处于 折叠状态</param>
        /// <returns>如果销毁成功则返回 true, 否则返回 false</returns>
        public virtual bool TryDestroy(out bool hide1, out bool hide2)
        {
            hide1 = hide2 = false;
            return false;
            ////Console.WriteLine("TryDestroy: " + this.ToString());

            //hide1 = hide2 = true;
            //var idePanel = this.IDEPanel;

            //var ctrl1 = idePanel == null ? null : idePanel.FindGroupOrSplitOrCenter(this.Panel1, out hide1);
            //var ctrl2 = idePanel == null ? null : idePanel.FindGroupOrSplitOrCenter(this.Panel2, out hide2);

            //if (ctrl1 == null && ctrl2 == null)
            //{
            //    #region  完全销毁

            //    this.Parent = null;
            //    this.Dispose();
            //    return true;

            //    #endregion
            //}
            //if ((ctrl1 == null && ctrl2 != null) || (ctrl2 == null && ctrl1 != null))
            //{
            //    #region  执行合并

            //    var parent = this.Parent;
            //    //if (parent != null) parent.SuspendLayout();
            //    var ctrl = ctrl1 ?? ctrl2;
            //    ctrl.Bounds = parent.Bounds;
            //    ctrl.Parent = parent; //(parent is IDEPanel) ? ((IDEPanel) parent).CenterPanel : parent;

            //    this.Parent = null;
            //    this.Dispose();
            //    //if (parent != null) parent.ResumeLayout();
            //    return true;

            //    #endregion
            //}

            return false;
        }

        #endregion


        protected virtual void OnPaint(Graphics g)
        {
            var bounds = this.Bounds;
            if (bounds.Width <= 0 || bounds.Height <= 0) return;
            GUIHelper.FillBack(g, GUIHelper.GetRandomColor(), bounds, true);
        }
        public override string ToString()
        {
            return "XIDESplitControl: " + this.Name;
        }


        public virtual void Dispose()
        {
            if (m_Panel1 != null) m_Panel1.Dispose();
            if (m_Panel2 != null) m_Panel2.Dispose();
            if (m_IDEPanel != null) m_IDEPanel.UnRegSplitControl(this);
            this.IsDisposed = true;
        }
    }

    public class XIDESplitPanel : IDisposable
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="owner">Type: XIDESplitControl</param>
        public XIDESplitPanel(XIDESplitControl owner)
        {
            if (owner == null) throw new ArgumentNullException("owner");
            this.m_Owner = owner;
        }


        protected XIDESplitControl m_Owner;
        protected object m_Child = null;
        protected bool m_IsCenter = false;
        protected Rectangle m_Bounds = Rectangle.Empty;

        /// <summary>
        /// 
        /// </summary>
        public InkFx.WinControl.XIDESplitControl Owner
        {
            get { return this.m_Owner; }
        }
        public object Child
        {
            get { return m_Child; }
        }
        public XIDESplitControl Split
        {
            get { return m_Child as XIDESplitControl; }
        }
        public XIDEGroup Group
        {
            get { return m_Child as XIDEGroup; }
        }
        public Rectangle Bounds
        {
            get { return m_Bounds; }
            set
            {
                m_Bounds = value;
                this.ResetRect();
            }
        }

        public bool IsDisposed { get; private set; }

        public bool IsCenter
        {
            get { return m_IsCenter; }
            set
            {
                m_IsCenter = value;
                this.Owner.InitFixedPanel();
            }
        }
        public bool IsHidden
        {
            get
            {
                if (this.IsCenter) return false;
                if (this.Child == null) return true;

                var group = this.Group;
                var split = this.Split;
                if (group != null && (group.Disposing || group.IsDisposed)) return true;
                if (group != null && group.State != XIDEGroupState.Expand) return true;
                if (split != null && split.Panel1Hidden && split.Panel2Hidden) return true;
                return false;
            }
        }

        public bool ContainsCenter
        {
            get
            {
                if (this.IsCenter) return true;
                var split = this.Split;
                if (split == null) return false;
                if (split.Panel1.ContainsCenter) return true;
                if (split.Panel2.ContainsCenter) return true;
                return false;
            }
        }
        public void ResetRect()
        {
            var child = this.Child;
            if (child == null) return;

            var bounds = this.Bounds;
            if (child is XIDEGroup)
            {
                //调整 Group 的尺寸
                var group = (XIDEGroup)child;
                var rect = (bounds.Width <= 0 || bounds.Height <= 0) ? Rectangle.Empty : bounds;
                group.Bounds = rect;
            }
            else if (child is XIDESplitControl)
            {
                var split = (XIDESplitControl)child;
                var rect = (bounds.Width <= 0 || bounds.Height <= 0) ? Rectangle.Empty : bounds;
                split.Bounds = rect;
            }
        }

        private Rectangle GetRealBounds(Rectangle bounds)
        {
            return bounds;

            var owner = this.m_Owner;
            var idePanel = owner == null ? null : owner.IDEPanel;
            if (idePanel == null) return Rectangle.Empty;

            var parent = idePanel.FindParentSplit(this);
        }
        public virtual void SetChild(object child)
        {
            if (child == null) { m_Child = null; return; }
            if (!(child is XIDEGroup || child is XIDESplitControl)) throw new ArgumentOutOfRangeException("child", "XIDESplitPanel.Child 必须是 XIDEGroup 或 XIDESplitControl 类型");
            this.m_Child = child;
            this.Owner.InitFixedPanel();
            this.ResetRect();
        }

        public virtual void Dispose()
        {
            IsDisposed = true;
        }
        public override string ToString()
        {
            return "XIDESplitPanel: " + (this.Split != null ? this.Split.Name : (this.Group != null ? this.Group.Name : ""));
        }
    }

}
